package com.lbd.gulimall.auth.controller;

import com.alibaba.fastjson.TypeReference;
import com.lbd.common.constrant.CommonAuthConstrant;
import com.lbd.common.exception.BizCodeEnum;
import com.lbd.common.utils.R;
import com.lbd.gulimall.auth.constrant.AuthConstrant;
import com.lbd.gulimall.auth.feign.MemberFeignService;
import com.lbd.gulimall.auth.feign.SmsFeignService;
import com.lbd.gulimall.auth.properties.SmsProperties;
import com.lbd.common.to.MemberEntity;
import com.lbd.gulimall.auth.vo.UserLoginVO;
import com.lbd.gulimall.auth.vo.UserRegisterVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author: linbd
 * @Description:
 * @Date: 2023/3/18 13:29
 */
@Controller
@EnableConfigurationProperties(SmsProperties.class)
@Slf4j
public class LoginController {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private SmsFeignService smsFeignService;
    @Autowired
    private SmsProperties smsProperties;
    @Autowired
    private MemberFeignService memberFeignService;

    @ResponseBody
    @GetMapping("/sms/getRegisterCode")
    public R getRegisterCode(@RequestParam("phone") String phone) {
        log.info("SmsProperties => {}", smsProperties);
        long l = System.currentTimeMillis();
        String key = AuthConstrant.REGISTER_CODE_PREFIX + phone;
        //code_时间戳
        String value = stringRedisTemplate.opsForValue().get(key);
        if (!StringUtils.isEmpty(value)) {
            String[] split = value.split("_");
            Long timeStamp = Long.valueOf(split[1]);
            if (l - timeStamp < smsProperties.getLimitTime()) {
                //发送频率达到阈值
                return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_CODE_EXCEPTION.getMsg());
            }
        }
        //如果key不存在 或 key存在并大于限流阈值60s。就可以重新生成验证码并发送短信
        String code = UUID.randomUUID().toString().substring(0, 4);
        R r = smsFeignService.sendSMS(phone, code);
        if (r.getCode() == 0) {
            //验证码发送短信成功
            stringRedisTemplate.opsForValue().set(key, code + "_" + l, smsProperties.getExpireTime(), TimeUnit.MINUTES);
            return R.ok();
        } else {
            //发送失败
            return R.error(BizCodeEnum.SMS_SEND_EXCEPTION.getCode(), BizCodeEnum.SMS_SEND_EXCEPTION.getMsg());
        }
    }

    @PostMapping("/register")
    public String register(@Valid UserRegisterVO userRegisterVO, BindingResult result, RedirectAttributes model) {
        if (result.hasErrors()) {
            Map<String, String> errors = result.getFieldErrors().stream()
                    .collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
            model.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/reg.html";
        }
        //注册
        String code = userRegisterVO.getCode();
        String key = AuthConstrant.REGISTER_CODE_PREFIX + userRegisterVO.getPhone();
        String value = stringRedisTemplate.opsForValue().get(key);
        if (!StringUtils.isEmpty(value)) {
            String[] split = value.split("_");
            if (code.equals(split[0])) {
                //为保证令牌机制，当验证码参与注册校验成功后，应该手动进行删除
                stringRedisTemplate.delete(AuthConstrant.REGISTER_CODE_PREFIX + userRegisterVO.getPhone());
                R r = memberFeignService.register(userRegisterVO);
                if (r.getCode() == 0) {
                    //登陆成功重定向到登录页 （重定向防止重复提交）
                    return "redirect:http://auth.gulimall.com/login.html";
                } else {
                    String msg = r.getData("msg", new TypeReference<String>() {
                    });
                    Map<String, String> errors = new HashMap<>();
                    errors.put("msg", msg);
                    model.addFlashAttribute("errors", errors);
                    return "redirect:http://auth.gulimall.com/reg.html";
                }
            } else {
                Map<String, String> errors = new HashMap<>();
                errors.put("code", "验证码不一致，请重新输入");
                model.addFlashAttribute("errors", errors);
                return "redirect:http://auth.gulimall.com/reg.html";
            }
        } else {
            Map<String, String> errors = new HashMap<>();
            errors.put("code", "验证码已过期，请重新获取");
            model.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/reg.html";
        }
    }


    @PostMapping("/login")
    public String login(UserLoginVO userLoginVO, RedirectAttributes model, HttpSession session) {
        R r = memberFeignService.login(userLoginVO);
        if (r.getCode() == 0) {
            MemberEntity member = r.getData(new TypeReference<MemberEntity>() {
            });
            //分布式session不共享，product服务拿不到这个值。
            session.setAttribute(CommonAuthConstrant.LOGIN_USER, member);
            return "redirect:http://gulimall.com";
        } else {
            String msg = r.getData("msg", new TypeReference<String>() {
            });
            Map<String, String> errors = new HashMap<>();
            errors.put("msg", msg);
            model.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/login.html";
        }
    }

    @GetMapping("/logout")
    public String logout(HttpSession session) {
        session.removeAttribute(CommonAuthConstrant.LOGIN_USER);
        return "redirect:http://gulimall.com";
    }

    @GetMapping("/login.html")
    public String toLogin(HttpSession session) {
        //从redis获取session。如果不为空说明已经登录过，重定向到主页。反之跳去登录页
        Object user = session.getAttribute(CommonAuthConstrant.LOGIN_USER);
        if (user == null) {
            return "login";
        }else {
            return "redirect:http://gulimall.com";
        }
    }
}
